package com.tanhua.dubbo.api;

import cn.hutool.core.collection.CollectionUtil;
import com.tanhua.dubbo.api.mongo.ReportApi;
import com.tanhua.model.mongo.Friend;
import com.tanhua.model.mongo.Report;
import com.tanhua.model.mongo.UserLike;
import org.apache.dubbo.config.annotation.DubboService;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@DubboService
public class ReportApiImpl implements ReportApi {

    @Autowired
    private MongoTemplate mongoTemplate;


    /**
     * 记录结论
     *
     * @param report
     * @return
     */
    @Override
    public String save(Report report) {
        long current = System.currentTimeMillis();
        Query query = new Query(Criteria.where("userId").is(report.getUserId())
                .and("questionnaireId").is(report.getQuestionnaireId()));
        Report one = mongoTemplate.findOne(query, Report.class);
        if(null != one) {
            Update update = new Update();
            update.set("conclusion", report.getConclusion());
            update.set("score", report.getScore());
            update.set("cover", report.getCover());
            update.set("updated", current);
            mongoTemplate.updateFirst(query, update, Report.class);
            return one.getId().toHexString();
        }

        report.setId(new ObjectId());
        report.setCreated(current);
        report.setUpdated(current);
        mongoTemplate.insert(report);
        return report.getId().toHexString();
    }

    /**
     * 获取报告
     *
     * @param reportId
     * @return
     */
    @Override
    public Report get(String reportId) {
        return mongoTemplate.findById(new ObjectId(reportId), Report.class);
    }

    /**
     * 获取相似分数的报告
     *
     * @param userId
     * @param score
     * @param level
     * @return
     */
    @Override
    public List<Report> getSimilarScore(Long userId, Double score, Integer level, String gender) {
        //查询好友ids
        Query friendQuery = new Query(Criteria.where("userId").is(userId));
        List<Friend> friends = mongoTemplate.find(friendQuery, Friend.class);
        List<Long> friendIds = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(friends)) {
            friendIds = friends.stream().map(Friend::getFriendId).collect(Collectors.toList());
        }
        //查询不喜欢的用户ids
        Query userLikeQuery = new Query(Criteria.where("userId").is(userId).and("isLike").is(false));
        List<UserLike> userLikes = mongoTemplate.find(userLikeQuery, UserLike.class);
        List<Long> userLikeIds = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(userLikes)) {
            userLikeIds = userLikes.stream().map(UserLike::getLikeUserId).collect(Collectors.toList());
        }

        //排除的ids
        List<Long> excludeIds = CollectionUtil.unionAll(friendIds, userLikeIds);
        excludeIds.add(userId);
        // 上下相差3分 按照更新时间的降序排序 最多查询10条
        double min = score - 3d;
        double max = score + 3d;
        Criteria criteria = new Criteria();
        criteria.andOperator(Criteria.where("score").gte(min), Criteria.where("score").lte(max));
        criteria.and("level").is(level).and("gender").is(gender).and("userId").nin(excludeIds);
        Query query = new Query();
        query.addCriteria(criteria).with(Sort.by(Sort.Direction.DESC, "updated")).limit(10);
        return mongoTemplate.find(query, Report.class);
    }

    /**
     * 根据问卷表查询结果
     *
     * @param userId
     * @param questionnaireId
     */
    @Override
    public Report getByQuestionnaireId(Long userId, ObjectId questionnaireId) {
        Query query = new Query(Criteria.where("userId").is(userId)
                .and("questionnaireId").is(questionnaireId));
        return mongoTemplate.findOne(query, Report.class);
    }
}
